package testing

import "fmt"

func main() {

	/*
		五. 递归函数

			在函数内部，可以调用其他函数。如果一个函数在内部调用自身，那么这个函数就是递归函数。递归函数必须满足以下两个条件：
				1. 在每一次调用自己时，必须是（在某种意义上）更接近于解；
				2. 必须有一个终止处理或计算的准则

			TIPS：
				· 递归函数的优点是定义简单，逻辑清晰。理论上，所有的递归函数都可以用循环的方式实现，但循环的逻辑不如递归清晰；
				· 使用递归函数需要注意防止栈溢出。在计算机中，函数调用是通过栈（stack）这种数据结构实现的，每当进入一个函数调用，栈就会加一层，
		          每当函数返回，栈就会减一层。由于栈的大小不是无限的，所以，递归调用的次数过多，会导致栈溢出；
				· 使用递归函数的优点是逻辑简单清晰，缺点是过深的调用会导致栈溢出
	*/
	fmt.Println("10!为：", recursion(10))
	fmt.Println("10!为：", recursion2(10))
	fmt.Println("10!为：", tailRecursion(10, 1))
}

/**
给出一个非负正整数n，计算阶乘 n!（递归方式）
*/
func recursion(total int) int {

	if total == 0 {
		return 1
	}

	return total * recursion(total-1)
}

/*
尾递归方式
*/
func tailRecursion(n1, n2 int) int {

	if n1 == 0 {
		return n2
	}

	return tailRecursion(n1-1, n1*n2)
}

/**
给出一个非负正整数n，计算阶乘 n!（循环方式）
*/
func recursion2(total int) int {

	result := 1

	if total == 0 {
		return result
	}

	for i := 1; i <= total; i++ {
		result *= i
	}
	return result
}
